package com.saturn.titan.util;

import java.net.URI;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class URIResolver {

	private static Logger logger = LoggerFactory.getLogger(URIResolver.class);

	public static final String[] IGNORED_PREFIX = new String[] { "javascript:", "mailto:" };
	protected URI base;
	protected LinkNormalizer linkNormalizer = new LinkNormalizer();

	public URIResolver() {
	}

	public URIResolver(URI base) {
		if (base == null)
			throw new IllegalArgumentException("base cannot be null");
		this.base = base;
	}

	public URI resolve(String link) {
		URI result = null;
		try {
			String target = linkNormalizer.normalize(link);
			target = linkNormalizer.escape(target);

			for (String ignored : IGNORED_PREFIX) {
				if (target.indexOf(ignored) != -1)
					return null;
			}

			int queryStringIndex = target.indexOf('?'); // to detect if http:// exists in query string
			int namedAnchorIndex = target.length() > 0 ? target.indexOf('#') : -1;
			if (namedAnchorIndex != -1 && namedAnchorIndex > queryStringIndex)
				target = target.substring(0, namedAnchorIndex);

			if (target.length() == 0) {
				result = base;
			} else if (target.substring(0, queryStringIndex != -1 ? queryStringIndex : target.length()).indexOf("://") != -1) {
				result = new URI(target);
			} else {
				if (target.charAt(0) == '?') {
					target = base.getPath() + target;
				} else if (target.startsWith("./")) {
					target = target.substring("./".length(), target.length());
				}

				if ((base.getPath() == null || "".equals(base.getPath())) && !target.startsWith("/")) {
					target = "/" + target;
				}

				result = base.resolve(target);
			}
		} catch (Exception e) {
			logger.error("URI is not valid - link: " + link + ", base: " + base + ", e: " + e.getMessage());
		}
		
		if (logger.isTraceEnabled())
			logger.trace("resolve() - resolved - result: " + result + ", link: " + link + ", base: " + base);
		return result;
	}

	public String toString() {
		return super.toString() + ": base: " + base;
	}

}
